import { NodeTypes } from "./ast"

// tag开始结束类型
const enum TagType {
    Start,
    End
}

export function baseParse (content: string) {
    const context = createParserContext(content)
    return createRoot(parseChildren(context,[]))
}

function parseChildren (context,ancestors) {
    const nodes:any = []
    while(!isEnd(context,ancestors)) {
        let node
        const s = context.source
        if (s.startsWith("{{")) {
            node = parseInterpolation(context)
        } else if (s[0] === "<") {
            if(/[a-z]/i.test(s[1])) {
                node = parseElement(context,ancestors)
            }
        } else {
            node = parseText(context)
        }
        nodes.push(node)
    }
    return nodes;
}

function isEnd(context,ancestors) {
    // 2. 当遇到结束标签的时候
    const s = context.source
    if(s.startsWith(`</`)) {
        for (let i = ancestors.length - 1; i >= 0; i--) {
            const tag = ancestors[i].tag;
            if(startsWithEndTagOpen(s,tag)) {
                return true
            }
        }
    }
    // 1. source 有值的时候
    return !s
}

// 截取 + 推进
function parseTextData(context,length) {
    const content = context.source.slice(0,length)
    advanceBy(context,length)
    return content
}

// 解析element功能
function parseElement(context,ancestors) {
    const element:any = parseTag(context,TagType.Start)
    ancestors.push(element)
    element.children = parseChildren(context,ancestors)
    
    ancestors.pop()
    
    if(startsWithEndTagOpen(context.source,element.tag)) {
        parseTag(context,TagType.End)
    } else {
        throw new Error(`缺少结束标签:${element.tag}`)
    }
    return element
}

// 对比字符串截取的tag和栈里的tag是否相同
function startsWithEndTagOpen(source,tag) {
    return source.startsWith("</") && source.slice(2,2 + tag.length).toLowerCase() === tag
}

// 解决text功能
function parseText(context: any) {
    let endIndex = context.source.length
    let endTokens = ["<","{{"]
    for (let i = 0; i < endTokens.length; i++) {
        const index = context.source.indexOf(endTokens[i])
        if(index !== -1 && endIndex > index) {
            endIndex = index
        } 
    }
    
    // 获取context
    const content = parseTextData(context,endIndex)
    
    return {
        type:NodeTypes.TEXT,
        content
    }
}

// 解决插值功能
function parseInterpolation (context) {
    // {{ message}}
    const openDelimiter = "{{";
    const closeDelimiter = "}}";
    
    // indexOf：第一个参数是查找的内容，第二个参数是从第几个开始找
    const closeIndex = context.source.indexOf(closeDelimiter,openDelimiter.length)
    
    // 清空插值
    advanceBy(context,openDelimiter.length)

    const rawContentLength = closeIndex - openDelimiter.length

    const rowContent = parseTextData(context,rawContentLength)
    // 去除插值里边的空格
    const content = rowContent.trim()

    advanceBy(context,closeDelimiter.length)

    return {
        type:NodeTypes.INTERPOLATION,
        content:{
            type:NodeTypes.SIMPLE_EXPRESSION,
            content:content
        }
    }
}

// 1.解析tag
function parseTag(context:any,type:TagType) {
    const match:any = /^<\/?([a-z]*)/i.exec(context.source)
    // console.log('match', match);
    
    const tag = match[1]
    
    // 2.删除处理完成的代码
    advanceBy(context, match[0].length)
    advanceBy(context, 1)
    if(type === TagType.End) return
    
    return {
        type:NodeTypes.ELEMENT,
        tag:tag
    }
}

function advanceBy(context: any, length: number) {
    context.source = context.source.slice(length)
}

function createParserContext(content: string) {
    return {
        source:content
    }
}

function createRoot(children) {
    return {
        children,
        type: NodeTypes.ROOT
    }
}





